package com.subfg.common.util.analysis;


import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.subfg.common.annotation.Analysis;
import com.subfg.common.entity.common.CommonParam;
import com.subfg.common.util.auth.AesUtil;
import com.subfg.common.util.common.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.MethodParameter;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.ModelAndViewContainer;
import org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodArgumentResolver;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.lang.reflect.Type;
import java.util.List;

public class AnalysisHandlerMethodArgumentResolver extends AbstractMessageConverterMethodArgumentResolver {
    private Logger log = LoggerFactory.getLogger(AnalysisHandlerMethodArgumentResolver.class);
    public AnalysisHandlerMethodArgumentResolver(List<HttpMessageConverter<?>> converters) {
        super(converters);
    }

    public AnalysisHandlerMethodArgumentResolver(List<HttpMessageConverter<?>> converters, List<Object> requestResponseBodyAdvice) {
        super(converters, requestResponseBodyAdvice);
    }

    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        return parameter.hasParameterAnnotation(Analysis.class);
    }

    @Override
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
        parameter = parameter.nestedIfOptional();
        Object arg = this.readWithMessageConverters(webRequest, parameter, parameter.getNestedGenericParameterType());
        Analysis analysis = parameter.getParameterAnnotation(Analysis.class);
        CommonParam commonParam = null;
        try {
            commonParam = new ObjectMapper().convertValue(arg, CommonParam.class);
            String authKey = commonParam.getAuthToken();
            // 判断请求是否为解密内容, 如 密钥 或 密钥不正确则进行解密, 确保请求的安全性
            if (StringUtil.isEmpty(authKey) || !authKey.equals("hVPXgh2mBb3s3ARzE9uWNcOjZaR86KDN")) {
               String decode = AesUtil.frontAesDecrypt(commonParam.getEncryptString());
               commonParam.setEncryptString(null);
               commonParam.setData(JSONObject.parseObject(decode, Object.class));
            }
        } catch (Exception e) {
            log.error("Required request body decrypt encypt: " + e);
        }
        return commonParam;
    }


    protected <T> Object readWithMessageConverters(NativeWebRequest webRequest, MethodParameter parameter, Type paramType) throws IOException, HttpMediaTypeNotSupportedException, HttpMessageNotReadableException {
        HttpServletRequest servletRequest = (HttpServletRequest)webRequest.getNativeRequest(HttpServletRequest.class);
        ServletServerHttpRequest inputMessage = new ServletServerHttpRequest(servletRequest);
        Object arg = this.readWithMessageConverters(inputMessage, parameter, paramType);
        if (arg == null && this.checkRequired(parameter)) {
            throw new HttpMessageNotReadableException("Required request body is missing: " + parameter.getExecutable().toGenericString(), inputMessage);
        } else {
            return arg;
        }
    }

    protected boolean checkRequired(MethodParameter parameter) {
        Analysis analysis = (Analysis) parameter.getParameterAnnotation(Analysis.class);
        return analysis != null && analysis.required() && !parameter.isOptional();
    }
}
